<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { onOpenContextMenu, invokeMenuAction } from '../assets/menus';

const isOpen = ref(false);
const rootPos = reactive({ x: 0, y: 0 });
const stack = ref([]); // [{ items, x, y, anchorEl, selected }]
const ctxRef = ref(null);
let disposeBus = null;
let lastOpenAt = { x: 0, y: 0 };

function close() {
  isOpen.value = false;
  stack.value = [];
}

function open(payload) {
  const { items, at, ctx } = payload || {};
  ctxRef.value = ctx || null;
  lastOpenAt = at || { x: 0, y: 0 };
  rootPos.x = Math.max(0, lastOpenAt.x || 0);
  rootPos.y = Math.max(0, lastOpenAt.y || 0);
  stack.value = [{ items: items || [], x: rootPos.x, y: rootPos.y, anchorEl: null, selected: -1 }];
  isOpen.value = true;
  nextTick(adjustRootPosition);
}

function adjustRootPosition() {
  const el = document.getElementById('ctx-menu-0');
  if (!el) return;
  const rect = el.getBoundingClientRect();
  let x = rootPos.x;
  let y = rootPos.y;
  const vw = window.innerWidth;
  const vh = window.innerHeight;
  if (x + rect.width > vw) x = Math.max(0, vw - rect.width - 4);
  if (y + rect.height > vh) y = Math.max(0, vh - rect.height - 4);
  stack.value[0].x = x;
  stack.value[0].y = y;
}

function onGlobalDown(e) {
  // close if click outside any panel
  if (!isOpen.value) return;
  const panels = document.querySelectorAll('[data-ctx-panel="true"]');
  let inside = false;
  panels.forEach((p) => { if (p.contains(e.target)) inside = true; });
  if (!inside) close();
}

function onKey(e) {
  if (!isOpen.value) return;
  const level = stack.value.length - 1;
  const cur = stack.value[level];
  if (!cur) return;
  const max = cur.items.length - 1;
  if (e.key === 'Escape') { e.preventDefault(); close(); return; }
  if (e.key === 'Tab') { e.preventDefault(); close(); return; }
  if (e.key === 'ArrowDown') {
    e.preventDefault();
    let idx = cur.selected;
    do { idx = (idx + 1) > max ? 0 : idx + 1; } while (isSeparatorOrHidden(cur.items[idx]));
    cur.selected = idx;
    return;
  }
  if (e.key === 'ArrowUp') {
    e.preventDefault();
    let idx = cur.selected;
    do { idx = (idx - 1) < 0 ? max : idx - 1; } while (isSeparatorOrHidden(cur.items[idx]));
    cur.selected = idx;
    return;
  }
  if (e.key === 'ArrowRight') {
    e.preventDefault();
    const it = cur.items[cur.selected];
    if (it && Array.isArray(it.submenu) && it.submenu.length) {
      openSubmenu(level, cur.selected, it);
    }
    return;
  }
  if (e.key === 'ArrowLeft') {
    e.preventDefault();
    if (stack.value.length > 1) stack.value.pop();
    return;
  }
  if (e.key === 'Enter') {
    e.preventDefault();
    const it = cur.items[cur.selected];
    if (it) activate(it, e);
    return;
  }
}

function isSeparatorOrHidden(it) { return !it || it.label === '-' || it.visible === false; }

function itemClasses(it, active) {
  if (it.label === '-') return 'my-1 h-px bg-panel-border';
  const base = 'px-3 py-1.5 text-[12px] flex items-center gap-2 rounded transition-colors';
  if (it.enabled === false) {
    return base + ' text-muted-fg opacity-50 cursor-not-allowed pointer-events-none';
  }
  const color = active ? 'bg-app-bg text-app-fg' : 'text-panel-fg hover:bg-app-bg';
  return base + ' ' + color + ' cursor-pointer select-none';
}

function openSubmenu(level, index, it) {
  // close deeper levels first
  while (stack.value.length > level + 1) stack.value.pop();
  const rootEl = document.getElementById(`ctx-item-${level}-${index}`);
  const parentPanel = document.getElementById(`ctx-menu-${level}`);
  if (!rootEl || !parentPanel) return;
  const r = rootEl.getBoundingClientRect();
  const pr = parentPanel.getBoundingClientRect();
  let x = pr.right - 4;
  let y = r.top;
  const vw = window.innerWidth;
  const vh = window.innerHeight;
  // pre-measure width approx
  const width = 200;
  if (x + width > vw) x = Math.max(0, pr.left - width);
  // basic clamp for height
  if (y + 240 > vh) y = Math.max(0, vh - 240);
  stack.value.push({ items: it.submenu || [], x, y, anchorEl: rootEl, selected: -1 });
}

function onMouseEnter(level, idx, it) {
  // do not select separators or disabled/hidden items on hover
  if (!it || it.label === '-' || it.visible === false || it.enabled === false) return;
  const cur = stack.value[level];
  if (!cur) return;
  cur.selected = idx;
  if (it && Array.isArray(it.submenu) && it.submenu.length) openSubmenu(level, idx, it);
  else while (stack.value.length > level + 1) stack.value.pop();
}

function activate(it, e) {
  if (it.enabled === false || it.label === '-') return;
  invokeMenuAction(it, e);
  close();
}

onMounted(() => {
  disposeBus = onOpenContextMenu((payload) => {
    open(payload);
  });
  // use pointerdown for better cross-device responsiveness
  window.addEventListener('pointerdown', onGlobalDown, { capture: true });
  window.addEventListener('keydown', onKey, { capture: true });
});

onBeforeUnmount(() => {
  if (disposeBus) try { disposeBus(); } catch {}
  window.removeEventListener('pointerdown', onGlobalDown, { capture: true });
  window.removeEventListener('keydown', onKey, { capture: true });
});
</script>

<template>
  <div v-if="isOpen" class="fixed inset-0 z-50" data-ctx-root="true">
    <div class="absolute inset-0" @mousedown="close" />
    <template v-for="(lvl, li) in stack" :key="'menu-'+li">
      <div :id="'ctx-menu-'+li" class="absolute min-w-[180px] overflow-hidden rounded-md border border-panel-border bg-panel-bg text-panel-fg shadow-lg" data-ctx-panel="true"
           :style="{ left: lvl.x + 'px', top: lvl.y + 'px' }" role="menu">
        <div class="py-1">
          <template v-for="(it, ii) in lvl.items" :key="it.id || ii">
            <div v-if="it.label==='-'" :class="itemClasses(it, false)" role="separator"></div>
            <div v-else :id="'ctx-item-'+li+'-'+ii" :class="itemClasses(it, lvl.selected===ii)"
                 @mouseenter="onMouseEnter(li, ii, it)" @click.stop="activate(it, $event)"
                 role="menuitem" :aria-disabled="it.enabled === false">
              <span class="flex-1 truncate">{{ it.label }}</span>
              <span v-if="it.accelerator" class="ml-6 text-[11px] text-muted-fg">{{ it.accelerator }}</span>
              <span v-if="Array.isArray(it.submenu) && it.submenu.length" class="ml-2 text-[10px] text-muted-fg">▶</span>
            </div>
          </template>
        </div>
      </div>
    </template>
  </div>
  
</template>

<style>
/* Prevent text selection flicker in context menu */
[data-ctx-panel="true"] * { user-select: none; }
</style>


